package com.lenovo.mso2o.ui.fragment;

import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v7.widget.CardView;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.LongSparseArray;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.baidu.location.BDLocation;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MyLocationConfiguration;
import com.baidu.mapapi.map.MyLocationData;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.baidu.mapapi.search.core.CityInfo;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.core.SearchResult;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiBoundSearchOption;
import com.baidu.mapapi.search.poi.PoiCitySearchOption;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.baidu.mapapi.utils.CoordinateConverter;
import com.baidu.platform.comjni.map.basemap.BaseMapCallback;
import com.baidu.platform.comjni.map.basemap.b;
import com.lenovo.framework.base.BaseDialogFragment;
import com.lenovo.framework.base.InjectableFragment;
import com.lenovo.framework.conf.FConstants;
import com.lenovo.framework.rx.RxBus;
import com.lenovo.framework.service.LocationService;
import com.lenovo.framework.util.DLog;
import com.lenovo.framework.util.ReflectHelper;
import com.lenovo.framework.util.maputil.MapDistance;
import com.lenovo.framework.util.maputil.PoiOverlay;
import com.lenovo.mso2o.MSApplication;
import com.lenovo.mso2o.R;
import com.lenovo.mso2o.conf.MSConstants;
import com.lenovo.mso2o.entity.LocationEvent;
import com.lenovo.mso2o.entity.g.UploadLocation;
import com.lenovo.mso2o.entity.g.UploadLocationDao;
import com.lenovo.mso2o.ui.adapter.PoiSearchingDetailAdapter;
import com.lenovo.mso2o.util.CommonUtil;
import com.lenovo.mso2o.util.Utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Random;

import butterknife.Bind;
import butterknife.OnClick;

/**
 * Created by lenovo on 2016/2/29.
 */
public class POISearchResultFragment extends InjectableFragment implements TextWatcher, BaiduMap.OnMarkerClickListener, LocationService.LocationSuccessListener {

    @Bind(R.id.layout_map_search_bottom)
    CardView layoutBottom;
    @Bind(R.id.tv_map_detail_search_bottom_name)
    TextView nameTvBottom;
    @Bind(R.id.tv_map_detail_search_bottom_address)
    TextView addressTvBottom;
    @Bind(R.id.tv_map_detail_search_bottom_distance)
    TextView distanceTvBottom;
    @Bind(R.id.mMapView)
    MapView mMapView;
    @Bind(R.id.recycler_poi_activity)
    RecyclerView mRecyclerView;
    @Bind(R.id.layout_poi_detail_activity_header)
    LinearLayout headerLayout;
    @Bind(R.id.tv_poi_detail_activity_header)
    TextView tvHeader;
    @Bind(R.id.edt_tool_search_map)
    EditText mSearchView;
    @Bind(R.id.img_tool_back_map)
    ImageView ivBack;
    private BitmapDescriptor mCurrentMarker;
    private GeoCoder geoCoder;
    private PoiSearch mPoiSearch;
    private String city;
    private String mQuery;
    private LatLng mLatLng;
    PoiSearchingDetailAdapter poiAdapter;
    private Random random;
    private ServiceConnection serviceConnection;
    private int pageCapacity;
    private LocationEvent locationEvent_;
    private boolean locationReceived;
    private UploadLocationDao locationDao;
    public static BaseDialogFragment.DialogFragmentDismissListener callBackObj;
    private int firstVisibleItem = -1;

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        random = new Random();
        mPoiSearch = PoiSearch.newInstance();
        locationDao = MSApplication.getDaoSession().getUploadLocationDao();
    }

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = super.onCreateView(inflater, container, savedInstanceState);
        mMapView.getMap().setMyLocationEnabled(true);
        mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
        mSearchView.addTextChangedListener(this);
        Intent intent = new Intent(getContext().getApplicationContext(), LocationService.class);
        serviceConnection = LocationService.connection(this, intent);
        getActivity().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
        //获取地址值
        String valSearchName = getArguments().getString(FConstants.NAME_SEARCH_PLACE);
        mSearchView.setText(valSearchName);
        mSearchView.setSelection(mSearchView.getText().length());
        poiAdapter = new PoiSearchingDetailAdapter(null);
        //showDefaultLocations(valSearchName);
        return view;
    }

    @Override
    public int provideContentRes() {
        return R.layout.activity_res_poi_map;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        callBackObj = null;
        if (serviceConnection != null) {
            try {
                getActivity().unbindService(serviceConnection);
            } catch (Exception e) {
            }
            serviceConnection = null;
        }
        //在activity执行onDestroy时执行mMapView.onDestroy()，实现地图生命周期管理
        if (mMapView != null) {
            mMapView.onDestroy();
            mMapView = null;
        }
        if (mPoiSearch != null) {
            mPoiSearch.setOnGetPoiSearchResultListener(null);
            mPoiSearch.destroy();
            mPoiSearch = null;
        }
    }

    @Override
    protected void onFragmentInVisible(Bundle savedInstanceState) {

    }

    @Override
    protected void onFragmentVisible(Bundle savedInstanceState) {

    }

    @Override
    public void onResume() {
        super.onResume();
        //在activity执行onResume时执行mMapView. onResume ()，实现地图生命周期管理
        mMapView.onResume();
        if (!CommonUtil.isGPSEnable(getActivity())) {
            Toast.makeText(getActivity(), "无法定位,请开启或重启gps", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        //在activity执行onPause时执行mMapView. onPause ()，实现地图生命周期管理
        mMapView.onPause();
        LongSparseArray<b> sparseArray =
                ReflectHelper.getFieldValue(new BaseMapCallback(), "a");
        DLog.i("sparsearray", "" + sparseArray);
        if (sparseArray != null) {
            Method gc = ReflectHelper.getMethod(LongSparseArray.class, "gc");
            DLog.i("gc", "" + gc);
            try {
                DLog.i("fix callback", "clearing");
                gc.invoke(sparseArray);
            } catch (IllegalAccessException e) {
                DLog.p(e);
            } catch (InvocationTargetException e) {
                DLog.p(e);
            }
        }
    }

    OnGetPoiSearchResultListener poiListener = new OnGetPoiSearchResultListener() {
        public void onGetPoiResult(PoiResult result) {
            mPoiSearch.setOnGetPoiSearchResultListener(null);
            DLog.i(getClass().getName(), "--------------------- onGetPoiResult --------------------");
            if (result == null || result.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
                //Toast.makeText(getContext(), "未找到结果", Toast.LENGTH_LONG).show();
                return;
            }
            if (result.error == SearchResult.ERRORNO.NO_ERROR) {
                DLog.i(getClass().getName(), "NO_ERROR");
                final List<PoiInfo> poiInfos = result.getAllPoi();
                if (poiInfos == null || poiInfos.size() <= 0) {
                    mRecyclerView.setVisibility(View.INVISIBLE);
                    headerLayout.setVisibility(View.INVISIBLE);
                    layoutBottom.setVisibility(View.INVISIBLE);
                }
                if (poiInfos != null && poiInfos.size() > 0) {
                    DLog.i(getClass().getName(), "size = " + poiInfos.size());
                }
                poiAdapter.setList(poiInfos);
                //poiAdapter.setLatLng(latLng);
                mRecyclerView.setVisibility(View.VISIBLE);
                headerLayout.setVisibility(View.VISIBLE);
                layoutBottom.setVisibility(View.INVISIBLE);
                tvHeader.setText("共找到\" " + mQuery + "\"相关" + poiInfos.size() + "个结果");
                mRecyclerView.setHasFixedSize(true);
                mRecyclerView.setAdapter(poiAdapter);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mRecyclerView.setOnScrollChangeListener(new View.OnScrollChangeListener() {
                        @Override
                        public void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
                            int curr = ((LinearLayoutManager) (mRecyclerView.getLayoutManager())).findFirstCompletelyVisibleItemPosition();
                            onItemChange(curr);
                        }
                    });
                } else {
                    mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
                        @Override
                        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                            super.onScrolled(recyclerView, dx, dy);
                            int curr = ((LinearLayoutManager) (mRecyclerView.getLayoutManager())).findFirstCompletelyVisibleItemPosition();
                            onItemChange(curr);
                        }
                    });
                }
                mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
                mRecyclerView.setItemAnimator(new DefaultItemAnimator());
                PoiSearchingDetailAdapter.OnRecyclerViewItemClickListener itemClickListener = new PoiSearchingDetailAdapter.OnRecyclerViewItemClickListener() {
                    @Override
                    public void onItemClick(int position) {
                        LocationEvent locationEvent = new LocationEvent();
                        PoiInfo info = poiInfos.get(position);
                        locationEvent.setLocation(info.address);
                        locationEvent.setLat(info.location.latitude);
                        locationEvent.setLng(info.location.longitude);
                        if (callBackObj != null) {
                            Bundle bundle = new Bundle();
                            bundle.putString("address", info.name + " " + info.address);
                            bundle.putDouble("latitude", info.location.latitude);
                            bundle.putDouble("longtitude", info.location.longitude);
                            callBackObj.onRetrieveDialogFragmentData(bundle, MSConstants.FragmentType.DIALOG_SEARCH_FRAGMENT_MS);
                            callBackObj = null;
                            //getActivity().finish();
                        }

                        List<UploadLocation> existList = locationDao.queryBuilder().where(UploadLocationDao.Properties.Location.eq(info.name + " " + info.address)).list();
                        if (existList == null || existList.size() <= 0) {
                            UploadLocation location = new UploadLocation();
                            location.setLocation(info.name + " " + info.address);
                            location.setLatitude(info.location.latitude);
                            location.setLongtitude(info.location.longitude);
                            locationDao.insert(location);
                        }
                        getActivity().finish();
                    }
                };
                poiAdapter.setOnItemClickListener(itemClickListener);
                poiAdapter.setLatLng(mLatLng);
                mMapView.getMap().clear();
                PoiOverlay overlay = new MyPoiOverlay(mMapView.getMap());
                //mMapView.getMap().setOnMarkerClickListener(overlay);
                overlay.setData(result);
                overlay.addToMap();
                overlay.zoomToSpan();
                mMapView.getMap().setOnMarkerClickListener(POISearchResultFragment.this);
                return;
            }
            if (result.error == SearchResult.ERRORNO.AMBIGUOUS_KEYWORD) {
                DLog.i(getClass().getName(), "---------------------onGetPoiResult 3 -------------------------");
                // 当输入关键字在本市没有找到，但在其他城市找到时，返回包含该关键字信息的城市列表
                String strInfo = "在";
                for (CityInfo cityInfo : result.getSuggestCityList()) {
                    strInfo += cityInfo.city;
                    strInfo += ",";
                }
                strInfo += "找到结果";
                Toast.makeText(getContext(), strInfo, Toast.LENGTH_LONG)
                        .show();
            }
        }

        public void onGetPoiDetailResult(PoiDetailResult result) {
            //获取Place详情页检索结果
        }
    };

    @Override
    public void beforeTextChanged(CharSequence s, int start, int count, int after) {

    }

    @Override
    public void onTextChanged(CharSequence s, int start, int before, int count) {

    }

    @Override
    public void afterTextChanged(Editable s) {
        mPoiSearch.setOnGetPoiSearchResultListener(poiListener);
        final String query = s.toString();
        mQuery = query;

        if(locationReceived) {
            showPlaces(query);
        }else{
            //Toast.makeText(getActivity(), "还没定位呢", Toast.LENGTH_SHORT).show();
            new Handler(Looper.getMainLooper()).postDelayed(new Runnable() {
                @Override
                public void run() {
                    showPlaces(query);
                }
            }, 2000);
        }
    }

    private void showPlaces(final String keyword) {
        if (keyword == null || keyword.length() <= 0) {
            mRecyclerView.setVisibility(View.INVISIBLE);
            headerLayout.setVisibility(View.INVISIBLE);
            layoutBottom.setVisibility(View.INVISIBLE);
        }

        pageCapacity = random.nextInt(20) + 10;
        //获取的经纬度不为空：若有城市信息, 则直接搜索，若无城市信息，则根据经纬度反解码出城市信息，再搜索
        //经纬度为空：区域内检索
        if (mLatLng != null) {
            //mPoiSearch.searchNearby(new PoiNearbySearchOption().keyword(keyword).radius(Integer.MAX_VALUE).location(latLng).pageCapacity(20).sortType(PoiSortType.comprehensive));
            if(city == null){
                // 创建地理编码检索实例
                geoCoder = GeoCoder.newInstance();
                OnGetGeoCoderResultListener listener = new OnGetGeoCoderResultListener() {
                    // 反地理编码查询结果回调函数
                    @Override
                    public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
                        if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
                            // 没有检测到结果
                            Toast.makeText(getActivity(), "无法获取城市，请重试", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        city = result.getAddressDetail().city;
                        if(city == null){
                            Toast.makeText(getActivity(), "无法获取城市，请重试", Toast.LENGTH_SHORT).show();
                            return;
                        }
                        if (city.contains("市")) {
                            city = city.substring(0, city.length() - 1);
                        }
                        mPoiSearch.searchInCity((new PoiCitySearchOption())
                                .city(city)
                                .keyword(keyword)
                                .pageCapacity(pageCapacity)
                                .pageNum(0));
                    }

                    // 地理编码查询结果回调函数
                    @Override
                    public void onGetGeoCodeResult(GeoCodeResult result) {
                        if (result == null
                                || result.error != SearchResult.ERRORNO.NO_ERROR) {
                            // 没有检测到结果
                        }
                    }
                };
                // 设置地理编码检索监听者
                geoCoder.setOnGetGeoCodeResultListener(listener);
                geoCoder.reverseGeoCode(new ReverseGeoCodeOption().location(mLatLng));

            }else{
                mPoiSearch.searchInCity((new PoiCitySearchOption())
                        .city(city)
                        .keyword(keyword)
                        .pageCapacity(pageCapacity)
                        .pageNum(0));
            }

        } else {
            CoordinateConverter converter = new CoordinateConverter();
            converter.from(CoordinateConverter.CoordType.GPS);
            // sourceLatLng待转换坐标
            //东北 50.80388021930629|130.89661430611355
            //西南 20.152722420924178|83.68217077464115
            LatLng southwest = new LatLng(20.152722420924178, 83.68217077464115);// 西南
            LatLng northeast = new LatLng(50.80388021930629, 130.89661430611355);// 东北

            LatLngBounds latLngBounds = new LatLngBounds.Builder()
                                            /*.include(converter.coord(new LatLng(53.3472020000, 136.8129920000)).convert())
                                            .include(converter.coord(new LatLng(3.1449770000, 74.2466830000)).convert())*/
                    .include(converter.coord(southwest).convert())
                    .include(converter.coord(northeast).convert())
                    .build();
            mPoiSearch.searchInBound(new PoiBoundSearchOption().bound(latLngBounds).keyword(keyword).pageCapacity(pageCapacity).pageNum(0));
        }
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        DLog.i(getClass().getName(), "baby you just clicked me ... ");
        Button distanceBt = new Button(getContext());
        distanceBt.setWidth(80);
        distanceBt.setHeight(20);
        distanceBt.setBackgroundResource(R.drawable.bubble_background);
        Bundle bundle = marker.getExtraInfo();
        String name = bundle.getString("name");
        String address = bundle.getString("address");
        LatLng latLngMark = new LatLng(bundle.getDouble("latitude"), bundle.getDouble("longtitude"));
        locationEvent_ = new LocationEvent();
        locationEvent_.setLocation(address);
        locationEvent_.setLat(latLngMark.latitude);
        locationEvent_.setLng(latLngMark.longitude);
        DLog.i(getClass().getName(), name + "---" + address + "---" + latLngMark.latitude + "---" + latLngMark.longitude);
        layoutBottom.setVisibility(View.VISIBLE);
        headerLayout.setVisibility(View.INVISIBLE);
        mRecyclerView.setVisibility(View.INVISIBLE);
        nameTvBottom.setText(name);
        addressTvBottom.setText(address);
        String dis = MapDistance.getInstance().getDistance(mLatLng, latLngMark);
        distanceTvBottom.setText("距您" + dis);
        distanceBt.setText("距离 " + dis);
        distanceBt.setTextSize(10);
        distanceBt.setGravity(Gravity.CENTER);
        InfoWindow mInfoWindow = new InfoWindow(distanceBt, marker.getPosition(), -47);
        mMapView.getMap().showInfoWindow(mInfoWindow);
        return true;
    }

    //first visible item changed, move map
    public void onItemChange(int curr) {
        if (this.firstVisibleItem != curr || this.firstVisibleItem == -1) {
            MapStatus.Builder builder = new MapStatus.Builder();
            PoiInfo poiInfo = poiAdapter.getItem(curr);
            builder.target(poiInfo.location);
            MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(builder.build().target);
            mMapView.getMap().setMapStatus(u);
            this.firstVisibleItem = curr;
        }
    }

    private class MyPoiOverlay extends PoiOverlay {

        public MyPoiOverlay(BaiduMap baiduMap) {
            super(baiduMap);
        }
    }

    @Override
    public void onReceiveLocation(BDLocation location) {
        if(serviceConnection != null) {
            try{
                getActivity().unbindService(serviceConnection);
            }catch (Exception e){}
            serviceConnection = null;
        }
        DLog.i(getClass().getName(),"定位出结果");
        city = location.getCity();
        locationReceived = true;
        mLatLng = new LatLng(location.getLatitude(), location.getLongitude());
        if (city != null && city.contains("市")) {
            city = city.substring(0, city.length() - 1);
        }
        if (mMapView == null || mMapView.getMap() == null || mPoiSearch == null) {
            return;
        }
        mMapView.getMap().setMyLocationEnabled(true);
        MyLocationData locData = new MyLocationData.Builder()
                .accuracy(location.getRadius())
                        // 此处设置开发者获取到的方向信息，顺时针0-360
                .direction(0).latitude(location.getLatitude())
                .longitude(location.getLongitude()).build();
        mMapView.getMap().setMyLocationData(locData);
        mCurrentMarker = null;
        MyLocationConfiguration config = new MyLocationConfiguration(MyLocationConfiguration.LocationMode.NORMAL, true, mCurrentMarker);
        mMapView.getMap().setMyLocationConfigeration(config);
        //showPlaces(mQuery);
    }

    @OnClick(R.id.img_tool_back_map)
    public void clickBack() {
        DialogFragment search = new POISearchDialogFragment();
        Bundle b = new Bundle();
        b.putString(POISearchDialogFragment.TYPE_KEY, "site");
        search.setArguments(b);
        search.show(getChildFragmentManager(), POISearchDialogFragment.TAG);
        getActivity().finish();
    }

    @OnClick(R.id.layout_map_search_bottom)
    public void clickCardView() {
        if (locationEvent_ != null) {
            RxBus rxBus = MSApplication.getRxBus();
            rxBus.send(locationEvent_);
        }
        getActivity().finish();
    }

}

